home *** CD-ROM | disk | FTP | other *** search
- //--------------------------------------------------------------------------
- //
- // Copyright (c) 2002, Colin Granville
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or
- // without modification, are permitted provided that the following
- // conditions are met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- //
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following
- // disclaimer in the documentation and/or other materials
- // provided with the distribution.
- //
- // * The name Colin Granville may not be used to endorse or promote
- // products derived from this software without specific prior
- // written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- // OF THE POSSIBILITY OF SUCH DAMAGE.
- //
- //--------------------------------------------------------------------------
-
- #include "DrawOutputFont.h"
- #include "GfxFont.h"
- #include "GfxState.h"
- #include <math.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "ucompare.h"
- #include <iostream.h>
- #include "PdfDocEncoding.h"
- #include "GlobalParams.h"
- #include "iostream.h"
- #include "FontEncodingTables.h"
-
- #define DEFAULT_FONT_LIST_SIZE 14
-
- double charWidths[DEFAULT_FONT_LIST_SIZE][256];
-
- struct FontFace
- {
- const char* pdfName;
- const char* riscOsName;
- UnicodeToAcornMap* map;
- double* charWidth;
- } defaultFonts[DEFAULT_FONT_LIST_SIZE] = {
- {"Courier", "Corpus.Medium", 0, charWidths[0]},
- {"Courier-Bold", "Corpus.Bold", 0, charWidths[1]},
- {"Courier-Oblique", "Corpus.Medium.Oblique", 0, charWidths[2]},
- {"Courier-BoldOblique", "Corpus.Bold.Oblique", 0, charWidths[3]},
- {"Helvetica", "Homerton.Medium", 0, charWidths[4]},
- {"Helvetica-Bold", "Homerton.Bold", 0, charWidths[5]},
- {"Helvetica-Oblique", "Homerton.Medium.Oblique", 0, charWidths[6]},
- {"Helvetica-BoldOblique", "Homerton.Bold.Oblique", 0, charWidths[7]},
- {"Times-Roman", "Trinity.Medium", 0, charWidths[8]},
- {"Times-Bold", "Trinity.Bold", 0, charWidths[9]},
- {"Times-Italic", "Trinity.Medium.Italic", 0, charWidths[10]},
- {"Times-BoldItalic", "Trinity.Bold.Italic", 0, charWidths[11]},
- {"Symbol", "Sidney", 0, charWidths[12]},
- {"ZapfDingbats", "Selwyn", 0, charWidths[13]}
- };
-
- class InitDefaultFonts
- {
- public:
- UnicodeToAcornMap latin1;
- UnicodeToAcornMap symbol;
- UnicodeToAcornMap dingbats;
- InitDefaultFonts();
- } initDefaultFonts;
-
- InitDefaultFonts::InitDefaultFonts()
- : latin1(unicodeToAcornLatin1),
- symbol(unicodeToAcornSymbol),
- dingbats(unicodeToAcornDingbats)
- {
- int f;
- for (f=0;f<DEFAULT_FONT_LIST_SIZE;f++)
- {
- if (f==DEFAULT_FONT_LIST_SIZE-1) defaultFonts[f].map=&dingbats;
- else if (f==DEFAULT_FONT_LIST_SIZE-2) defaultFonts[f].map=&symbol;
- else defaultFonts[f].map=&latin1;
- }
-
- for (f=0;f<DEFAULT_FONT_LIST_SIZE;f++)
- {
- int handle=0;
- _swix(Font_FindFont,_INR(1,5) | _OUT(0), defaultFonts[f].riscOsName,16,16,0,0,&handle);
- if (handle)
- {
- int spacewidth=0;
- _swix(Font_ScanString,_INR(0,5) | _OUT(3), 0," ",0,-1,-1,0,&spacewidth);
- int i;
- for (i=0;i<32;i++) charWidths[f][i]=0;
- char s[4];
- s[0]=' ';s[2]=' ';s[3]=0;
- for (i=32;i<256;i++)
- {
- int size=spacewidth;
- s[1]=i;
- _swix(Font_ScanString,_INR(0,5) | _OUT(3), 0,s,0,-1,-1,0,&size);
- charWidths[f][i]=double(size-spacewidth)/1000.0;
- }
- if (f<DEFAULT_FONT_LIST_SIZE-2) charWidths[f][0x8f]=0;//dont alter shape of bullet
- _swix(Font_LoseFont,_IN(0),handle);
- }
- }
- }
-
- //*****************************************************************
- //*****************************************************************
- //*****************************************************************
-
- DrawOutputFontList::DrawOutputFontList()
- : fontList(0),
- handle(0)
- {
- flags=0;
- }
-
- //*****************************************************************
-
- DrawOutputFontList::~DrawOutputFontList() {clear();}
-
- //*****************************************************************
-
- void DrawOutputFontList::declareFonts()
- {
- int i;
- for (i=0;i<DEFAULT_FONT_LIST_SIZE;i++)
- {
- _swix(PDriver_DeclareFont,_INR(0,2),0,defaultFonts[i].riscOsName,0);
- }
- }
-
- //*****************************************************************
-
- const char* DrawOutputFontList::getUsedFont(int fontIndex)
- {
- fontIndex--;
- if (fontIndex<0 || fontIndex>=DEFAULT_FONT_LIST_SIZE) return 0;
- return defaultFonts[fontIndex].riscOsName;
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::clear()
- {
- lose();
-
- DrawOutputFont* f=fontList;
- DrawOutputFont* next=0;
- for (;f;f=next) {next=f->next;delete f;}
-
- fontList=0;
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::atExit()
- {
- lose();
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::find(GfxState& state)
- {
- if (fontList==0) return;
- double fontsize=(state.getFont() ? state.getFontSize() : 10.0);
- int newFontXSize= int(fontsize*matXScale*state.getHorizScaling()) ;
- if (newFontXSize<40) newFontXSize=40; //causes redraw problems if size < 1/16 pt
-
- int newFontYSize= (int)(fontsize*matYScale);
- if (newFontYSize<40) newFontYSize=40; //causes redraw problems if size < 1/16 pt
-
- if (font==fontList->getFontIndex() && newFontYSize==fontYSize && newFontXSize==fontXSize) return;
- fontXSize=newFontXSize;
- fontYSize=newFontYSize;
- font=fontList->getFontIndex();
- int oldhandle=handle;
- _swix(Font_FindFont,_INR(1,5) | _OUT(0), fontList->getRiscOsFontName(),
- fontXSize/40,
- fontYSize/40,
- 0,
- 0,
- &handle);
- if (oldhandle) _swix(Font_LoseFont,_IN(0),oldhandle);
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::lose()
- {
- if (handle)
- {
- _swix(Font_LoseFont,_IN(0),handle);
- handle=0;
- }
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::setMatrix(GfxState& state)
- {
- double* ctm=state.getCTM();
- double* tm=state.getTextMat();
-
- //calculate x scale
- double a = tm[0]*ctm[0] + tm[1]*ctm[2];
- double b = tm[0]*ctm[1] + tm[1]*ctm[3];
- double scale = sqrt(a*a+b*b);
- charMatrix[0]=(a*65536.0/scale);
- transform.m0 = (int)charMatrix[0];
- charMatrix[1]=(b*65536.0/scale);
- transform.m1 = (int)charMatrix[1];
- matXScale=scale;
-
- //calculate y scale
- a=tm[2]*ctm[0] + tm[3]*ctm[2];
- b=tm[2]*ctm[1] + tm[3]*ctm[3];
- scale=sqrt(a*a+b*b);
- transform.m2 = (int)(a*65536.0/scale);
- transform.m3 = (int)(b*65536.0/scale);
- matYScale=scale;
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::setCharMatrix(double fromWid, double toWid)
- {
- double scale= (fromWid!=0 && toWid !=0 ? fromWid/toWid :1.0);
- transform.m0=(int)(charMatrix[0]*scale);
- transform.m1=(int)(charMatrix[1]*scale);
- }
-
- //*****************************************************************
-
- void DrawOutputFontList::set(GfxState& state)
- {
- setMatrix(state);
- GfxFont* gfxFont=state.getFont();
- DrawOutputFont* f=fontList;
- DrawOutputFont* last=0;
- for (;f;last=f,f=f->next)
- {
- if (gfxFont==f->getFont())
- {
- if (last)
- {
- last->next=f->next;
- f->next=fontList;
- fontList=f;
- }
- find(state);
- return;
- }
- }
-
- f=new DrawOutputFont(gfxFont);
- if (f)
- {
- f->next=fontList;
- fontList=f;
- find(state);
- }
- }
-
- //*****************************************************************
- //*****************************************************************
- //*****************************************************************
-
- DrawOutputFont::DrawOutputFont(GfxFont* gfxFont)
- : font(gfxFont),
- mapStore(0)
- {
-
- if (!gfxFont)
- {
- getSubstituteFont(0);
- return;
- }
-
- GString*font_name=gfxFont->getName();
- if (!font_name) font_name = gfxFont->getEmbeddedFontName();
- if (!font_name || !findFont(font_name->getCString()))
- {
- getSubstituteFont(font_name?font_name->getCString():0);
- }
- return;
- }
-
- //*****************************************************************
-
- DrawOutputFont::~DrawOutputFont()
- {
- delete mapStore;
- }
-
- //*****************************************************************
-
- void DrawOutputFont::getSubstituteFont(const char* name)
- {
- if (font==0)
- {
- riscOsFontName=defaultFonts[0].riscOsName;
- map=defaultFonts[0].map;
- charWidth=defaultFonts[0].charWidth;
- fontIndex=1;
- return;
- }
-
- int i=4;
- if (name)
- {
- if (font->isSerif() ||
- uFind(name,"times") ||
- (!uFind(name,"sans") && uFind(name,"serif")) ||
- uFind(name,"Garamond")) i=8;
- if (font->isFixedWidth() || uFind(name,"courier")) i=0;
-
- if (font->isItalic() || uFind(name,"obli") || uFind(name,"ital") ) i|=2;
- if (font->isBold() || uFind(name,"bold")|| uFind(name,"black")) i|=1;
- }
- else i=8;//serif font
-
-
- map=defaultFonts[i].map;
- riscOsFontName=defaultFonts[i].riscOsName;
- charWidth=defaultFonts[i].charWidth;
- fontIndex=i+1;
- }
-
- //*****************************************************************
-
- bool DrawOutputFont::findFont(const char* name)
- {
- if (name==0) return 0;
- const char* n=name;
- while (!(*n==0 || *n=='+' || *n=='-')) n++;
- if (*n=='+') name=n+1;
- int i;
- for (i=0;i<DEFAULT_FONT_LIST_SIZE;i++)
- {
- if (uCompare(name,defaultFonts[i].pdfName)==0)
- {
- riscOsFontName=defaultFonts[i].riscOsName;
- map=defaultFonts[i].map;
- charWidth=defaultFonts[i].charWidth;
- fontIndex=i+1;
- return 1;
- }
- }
- return 0;
- }
-
- //*****************************************************************
- //*****************************************************************
- //*****************************************************************
-
- class StandardFontToAcornLatin1
- {
- public:
- StandardFontToAcornLatin1();
- unsigned char getChar(const unsigned char c) {return map[c];}
- private:
- unsigned char map[256];
-
- };
-
- StandardFontToAcornLatin1& standardFontToAcornLatin1()
- {
- static StandardFontToAcornLatin1 p;
- return p;
- }
-
- //*****************************************************************
-
- StandardFontToAcornLatin1::StandardFontToAcornLatin1()
- {
- for (int i=0;i<256;i++)
- {
- map[i]=0;
- char* name=pdfDocEncoding[i];
- if (name)
- {
- Unicode u=globalParams->mapNameToUnicode(name);
- if (u) map[i]=initDefaultFonts.latin1.getChar(u);
- }
- }
- }
- //*****************************************************************
-
- string toAcornLatin1(const char* str, int len)
- {
- string res;
- unsigned char* p=(unsigned char*)str;
-
- if (p[0]==0xfe && p[1]==0xff)
- {
- res.reserve(len/2);
- for (int i=2;i<len;i+=2)
- {
- unsigned char c=initDefaultFonts.latin1.getChar(p[i]+p[i+1]*256);
- if (c!=UnicodeToAcornMap::NO_CONVERSION_CHAR) res+=c;
- }
- }
- else if (p[0]==0xff && p[1]==0xfe)
- {
- res.reserve(len/2);
- for (int i=2;i<len;i+=2)
- {
- unsigned char c=initDefaultFonts.latin1.getChar(p[i+1]+p[i]*256);
- if (c!=UnicodeToAcornMap::NO_CONVERSION_CHAR) res+=c;
- }
- }
- else
- {
- StandardFontToAcornLatin1& s = standardFontToAcornLatin1();
- res.reserve(len);
- for (int i=0;i<len;i++)
- {
- unsigned char c = s.getChar(p[i]);
- if (c) res+=(char)c;
- }
- }
- return res;
- }
-